import numpy as np
import torch

# 张量入门
type = torch.tensor([1.2, 3.4]).dtype
print(type)

# 修改默认张量类型
torch.set_default_tensor_type(torch.DoubleTensor)
type = torch.tensor([1.2, 3.4]).dtype
print(type)

# 张量转换
a = torch.tensor([1.2, 3.4])
print(a.dtype)
print(a.long().dtype)
print(a.int().dtype)
print(a.float().dtype)


# 恢复张量类型
torch.set_default_tensor_type(torch.FloatTensor)
torch.tensor([1.2, 3.4])


# 获取默认张量类型
print(torch.get_default_dtype())

# 使用tensor生成张量
a = torch.tensor([[1.0, 1.0], [2, 2]])
print(a)

# 查看张量纬度
print(a.shape)

# 查看张量大小
print(a.size())

# 张量的元素个数
print(a.numel())


# 使用dtype指定张量类型，使用requires_grad 指定张量是否需要计算梯度
b = torch.tensor((1, 2, 3), dtype=torch.float32, requires_grad=True)
print(b)

# 计算b的sum（B2）的梯度大小
y = b.pow(2).sum()
y.backward()
print(b.grad)

# 只有浮点型的张量允许计算梯度！！！


# 使用Tensor() 创建张量
c = torch.Tensor([1, 2, 3, 4])
print(c)

# 创建特定大小的张量
d = torch.Tensor(2, 3)
print(d)

# 使用 ***like 放批量设置张量
torch.ones_like(d)
torch.zeros_like(d)
torch.rand_like(d)
print(d)

# 使用new_**创建一个类型相似，但尺寸不同的张量
e = [[1, 2], [3, 4]]
e = d.new_tensor(e)     # 将列表转换成张量
e = d.new_full((3, 3), fill_value=1)           # 创建3 * 3  使用1填充的张量
e = d.new_zeros((3, 3))                          # 创建3 * 3  使用0填充的张量
e = d.new_empty((3, 3))                          # 创建3 * 3 的空张量
e = d.new_ones((3, 3))                           # 创建3 * 3 的1张量


# Numpy转Tensor
f = np.ones((3, 3))
fTensor = torch.as_tensor(f)
print(fTensor)
fTensor = torch.from_numpy(f)

# Tensor转Numpy
f = fTensor.numpy()
print(f)


# 随机数生成张量  mean 是均值   std是标准差
torch.manual_seed(123)
a = torch.normal(mean=0.0, std=torch.tensor(1.0))
a = torch.normal(mean=0.0, std=torch.arange(1, 5.0))
a = torch.normal(mean=torch.arange(1, 5.0), std=torch.arange(1, 5.0))
print(a)


# 使用 torch.rand 生成均匀分布的张量
torch.manual_seed(123)
b = torch.rand(3, 4)
print(b)


# 使用torch.rand_like 根据其他张量生成纬度相同的随机张量
c = torch.ones(2, 3)
d = torch.rand_like(c)
print(d)


# 生成正态分布随机张量
e = torch.randn(3, 3)
e = torch.randn_like(c)
print(e)


# 使用randperm(n) 将 0 ~ n之间的整数进行随机排序后输出
f = torch.randperm(5)
print(f)

# 使用 arange() 生成范围张量
g = torch.arange(start=0, end=10, step=2)
print(g)

# 使用 linspace() 生成固定数量的等间隔的张量
h = torch.linspace(start=1, end=10, steps=5)
print(h)


# 使用 logspace 生成对数为间隔的张量
i = torch.logspace(start=0.1, end=1.0, steps=5)
print(i)
